package berlinatyourfingertips.apis.youtube;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import com.briansteen.utils.GeoPosition;
import com.google.gdata.client.youtube.YouTubeQuery;
import com.google.gdata.client.youtube.YouTubeService;
import com.google.gdata.data.geo.impl.GeoRssWhere;
import com.google.gdata.data.youtube.VideoEntry;
import com.google.gdata.data.youtube.VideoFeed;

public class YouTubeRequester
{
	private static YouTubeRequester _instance;
	
	private YouTubeService _service;
	
	/** The name of the server hosting the YouTube GDATA feeds */
	public static final String YOUTUBE_GDATA_SERVER = "http://gdata.youtube.com";
	
	/** The prefix common to all standard feeds */
	public static final String STANDARD_FEED_PREFIX = YOUTUBE_GDATA_SERVER + "/feeds/api/standardfeeds/";
	
	/** The URL of the "Most Recent" feed */
	public static final String MOST_RECENT_FEED = STANDARD_FEED_PREFIX + "most_recent";
	
	/** The URL of the "Top Rated" feed */
	public static final String TOP_RATED_FEED = STANDARD_FEED_PREFIX + "top_rated";
	
	/** The URL of the "Most Viewed" feed */
	public static final String MOST_VIEWED_FEED = STANDARD_FEED_PREFIX + "most_viewed";
	
	/** The URL of the "Recently Featured" feed */
	public static final String RECENTLY_FEATURED_FEED = STANDARD_FEED_PREFIX + "recently_featured";
	
	/** The URL of the "Watch On Mobile" feed */
	public static final String WATCH_ON_MOBILE_FEED = STANDARD_FEED_PREFIX + "watch_on_mobile";
	
	/** The URL of the "Videos" feed */
	public static final String VIDEOS_FEED = YOUTUBE_GDATA_SERVER + "/feeds/api/videos";
	
	/** The prefix of the User Feeds */
	public static final String USER_FEED_PREFIX = YOUTUBE_GDATA_SERVER + "/feeds/api/users/";
	
	/** The URL suffix of the test user's uploads feed */
	public static final String UPLOADS_FEED_SUFFIX = "/uploads";
	
	/** The URL suffix of the test user's favorites feed */
	public static final String FAVORITES_FEED_SUFFIX = "/favorites";
	
	/** The URL suffix of the test user's subscriptions feed */
	public static final String SUBSCRIPTIONS_FEED_SUFFIX = "/subscriptions";
	
	/** The URL suffix of the test user's playlists feed */
	public static final String PLAYLISTS_FEED_SUFFIX = "/playlists";
	
	public YouTubeRequester()
	{
		if(_instance == null)
		{
			_instance = this;
			
			this._service = new YouTubeService("FHP-YouTubeMockUp-1");
		}
		else throw new Error("YouTubeConnector is a Singleton and therefor can only be accessed trough YouTubeConnector.getInstance().");
	}
	
	public static YouTubeRequester getInstance()
	{
		if(_instance == null) _instance = new YouTubeRequester();
		return _instance;
	}
	
	public void printRecentVideos()
	{
		VideoFeed videoFeed = null;
		
		try
		{
			videoFeed = this._service.getFeed(new URL(MOST_RECENT_FEED), VideoFeed.class);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		if(videoFeed != null)
		{
			List<VideoEntry> videoEntries = videoFeed.getEntries();
			for(VideoEntry entry : videoEntries) printVideoProperties(entry);
		}
	}
	
	public ArrayList<GeoPosition> getRecentVideoPositions()
	{
		VideoFeed videoFeed = null;
		
		try
		{
			videoFeed = this._service.getFeed(new URL(MOST_RECENT_FEED), VideoFeed.class);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		if(videoFeed != null) return getGeoDataAsArrayList(videoFeed);
		return null;
	}
	
	public ArrayList<GeoPosition> getRecentVideoPositionsBerlin()
	{
		VideoFeed videoFeed = null;
		
		try
		{
			videoFeed = this._service.getFeed(new URL("http://gdata.youtube.com/feeds/api/videos/?max-results=50&orderby=published&location=52.30,13.22&location-radius=50km&v=2"), VideoFeed.class);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		if(videoFeed != null)
		{
			return this.getGeoDataAsArrayList(videoFeed);
		}
		
		return null;
	}
	
	public void printVideoSearchResult(String searchterm)
	{
		YouTubeQuery query = null;
	    VideoFeed videoFeed = null;
	    
	    try
	    {
	    	query = new YouTubeQuery(new URL(VIDEOS_FEED));
		    query.setSafeSearch(YouTubeQuery.SafeSearch.NONE);
		    query.setFullTextQuery(searchterm);
	    	
	    	videoFeed = this._service.query(query, VideoFeed.class);
	    }
	    catch(Exception e)
	    {
	    	e.printStackTrace();
	    }
		
		if(videoFeed != null)
		{
			List<VideoEntry> videoEntries = videoFeed.getEntries();
			for(VideoEntry entry : videoEntries) printVideoProperties(entry);
		}
	}
	
	public ArrayList<GeoPosition> getVideoSearchResultPositions(String searchterm)
	{
		YouTubeQuery query = null;
	    VideoFeed videoFeed = null;
	    
	    try
	    {
	    	query = new YouTubeQuery(new URL(VIDEOS_FEED));
		    query.setSafeSearch(YouTubeQuery.SafeSearch.NONE);
		    query.setFullTextQuery(searchterm);
	    	
	    	videoFeed = this._service.query(query, VideoFeed.class);
	    }
	    catch(Exception e)
	    {
	    	e.printStackTrace();
	    }
		
		if(videoFeed != null) return this.getGeoDataAsArrayList(videoFeed);
		return null;
	}
	
	private void printVideoProperties(VideoEntry videoEntry)
	{
		System.out.println(videoEntry.getTitle().getPlainText());
		
		GeoRssWhere geo = videoEntry.getGeoCoordinates();
		if(geo != null) System.out.println("Geo: " + geo.getLatitude() + " / " + geo.getLongitude());
		
		System.out.println("");
		System.out.println("");
	}
	
	private ArrayList<GeoPosition> getGeoDataAsArrayList(VideoFeed videoFeed)
	{
		ArrayList<GeoPosition> out = new ArrayList<GeoPosition>();
		GeoRssWhere geo;
		
		List<VideoEntry> videoEntries = videoFeed.getEntries();
		for(VideoEntry entry : videoEntries)
		{
			geo = entry.getGeoCoordinates();
			if(geo != null) out.add(new GeoPosition(geo.getLatitude().floatValue(), geo.getLongitude().floatValue()));
		}
		
		return out;
	}
}
